import pynput
import time

class TypeWriter:
    def __init__(self):
        self.existing_text: str = ''
        self.last_type_text: str = ''
        self.keyboard = pynput.keyboard.Controller()
        self.had_input: bool = False

    def revoke(self):
        self.do_revoke()

    def do_revoke(self):
        num_backspace = len(self.last_type_text)
        ret = self.last_type_text
        self.last_type_text = ''
        for _ in range(num_backspace):
            self.keyboard.tap(pynput.keyboard.Key.backspace)
        return ret

    def do_start(self):
        self.last_type_text = ''
        self.existing_text = ''

    def input(self, text: str, finish: bool):
        if not self.had_input:
            self.do_start()
            self.had_input = True
        self.do_input(text)
        if finish:
            self.had_input = False
            self.do_finish()

    def do_input(self, text: str):
        if text == self.existing_text:
            return
        # find common prefix
        if text.startswith(self.existing_text):
            i = len(self.existing_text)
        else:
            i = 0
            for i in range(min(len(text), len(self.existing_text))):
                c = text[i]
                if c != self.existing_text[i]:
                    break
        num_backspace = len(self.existing_text) - i
        suffix = text[i:]
        self.existing_text = text

        # delete existing text
        if num_backspace:
            for _ in range(num_backspace):
                self.keyboard.tap(pynput.keyboard.Key.backspace)
            time.sleep(0.06)

        # type new text
        if len(suffix) > 0:
            if all(x.isascii() for x in suffix):
                self.keyboard.type(suffix)
            else:
                for x in suffix:
                    with self.keyboard.pressed(pynput.keyboard.Key.ctrl):
                        with self.keyboard.pressed(pynput.keyboard.Key.shift):
                            self.keyboard.tap('u')
                    # time.sleep(0.01)
                    for c in '{:x}'.format(ord(x)):
                        self.keyboard.tap(c)
                    self.keyboard.tap(pynput.keyboard.Key.enter)
                # pyperclip.copy(suffix)
                # time.sleep(0.05)
                # with self.keyboard.pressed(pynput.keyboard.Key.ctrl):
                #     self.keyboard.tap('v')

    def cancel(self):
        self.do_cancel()

    def do_cancel(self):
        num_backspace = len(self.existing_text)
        for _ in range(num_backspace):
            self.keyboard.tap(pynput.keyboard.Key.backspace)
        self.last_type_text = self.existing_text
        self.existing_text = ''

    def do_finish(self, enter: bool = False):
        self.last_type_text = self.existing_text
        if self.existing_text and enter:
            self.keyboard.tap(pynput.keyboard.Key.enter)
            self.last_type_text += '\n'
        self.existing_text = ''

if __name__ == "__main__":
    tw = TypeWriter()
    tw.input('你好，这个残酷的世界，再见了', True)
